package com.adee.gulimall.gateway.filter;

import com.adee.gulimall.util.utils.JwtUtils;
import com.adee.gulimall.util.utils.R;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 用户身份认证、鉴权过滤器
 * 1.校验jwt，用户登录信息是否有效；
 * 2.校验用户是否有系统访问权限。
 */
@Component
@Slf4j
public class Global_3_AuthFilter implements GlobalFilter, Ordered {
        /**
         * 过滤器业务逻辑
         *
         * @param exchange
         * @param chain
         * @return
         */
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 从cookie中获取jwtToken
            HttpCookie first = exchange.getRequest().getCookies().getFirst(JwtUtils.header);
            String jwtToken = first == null ? null : first.getValue();
            // 校验jwtToken是否有效
            if (StringUtils.hasText(jwtToken) && JwtUtils.isValid(jwtToken)) {
                // 有效，继续执行后面的filter
                return chain.filter(exchange);
            }
            // 无效，直接返回401给客户端
            log.warn("token is not valid...");
            ServerHttpResponse response = exchange.getResponse();
            // 响应类型
            response.getHeaders().add("Content-Type",
                    "application/json;charset=utf-8");
            // 响应状态码，HTTP 401 错误代表用户没有访问权限
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            // 响应内容

            String body = JSON.toJSONString(R.error("用户未登录"));
            DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
            // 请求结束，不再继续向下请求
            return response.writeWith(Mono.just(buffer));
        }

        /**
         * 过滤器执行顺序，数值越小，优先级越高
         *
         * @return
         */
        @Override
        public int getOrder() {
            return OrderNum.AuthFilterOrder;
        }
}
